home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / unix / tkUnixFocus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  3.8 KB  |  133 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkUnixFocus.c --
  3.  *
  4.  *    This file contains platform specific procedures that manage
  5.  *    focus for Tk.
  6.  *
  7.  * Copyright (c) 1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tkUnixFocus.c 1.7 97/08/11 09:47:20
  13.  */
  14.  
  15. #include "tkInt.h"
  16. #include "tkPort.h"
  17. #include "tkUnixInt.h"
  18.  
  19. extern int tclFocusDebug;
  20.  
  21. /*
  22.  *----------------------------------------------------------------------
  23.  *
  24.  * TkpChangeFocus --
  25.  *
  26.  *    This procedure is invoked to move the official X focus from
  27.  *    one window to another.
  28.  *
  29.  * Results:
  30.  *    None.
  31.  *
  32.  * Side effects:
  33.  *    The official X focus window changes;  the application's focus
  34.  *    window isn't changed by this procedure.
  35.  *
  36.  *----------------------------------------------------------------------
  37.  */
  38.  
  39. void
  40. TkpChangeFocus(winPtr, force)
  41.     TkWindow *winPtr;        /* Window that is to receive the X focus. */
  42.     int force;            /* Non-zero means claim the focus even
  43.                  * if it didn't originally belong to
  44.                  * topLevelPtr's application. */
  45. {
  46.     TkDisplay *dispPtr = winPtr->dispPtr;
  47.     Tk_ErrorHandler errHandler;
  48.     Window window, root, parent, *children; 
  49.     unsigned int numChildren; 
  50.     TkWindow *winPtr2;
  51.     int dummy;
  52.  
  53.     /*
  54.      * Don't set the X focus to a window that's marked
  55.      * override-redirect.  This is a hack to avoid problems with menus
  56.      * under olvwm: if we move the focus then the focus can get lost
  57.      * during keyboard traversal.  Fortunately, we don't really need to
  58.      * move the focus for menus: events will still find their way to the
  59.      * focus window, and menus aren't decorated anyway so the window
  60.      * manager doesn't need to hear about the focus change in order to
  61.      * redecorate the menu.
  62.      */
  63.     if (winPtr->atts.override_redirect) {
  64.     return;
  65.     }
  66.  
  67.     /*
  68.      * Check to make sure that the focus is still in one of the windows
  69.      * of this application or one of their descendants.  Furthermore,
  70.      * grab the server to make sure that the focus doesn't change in the
  71.      * middle of this operation.
  72.      */
  73.  
  74.     XGrabServer(dispPtr->display);
  75.     if (!force) {
  76.     /*
  77.      * Find the focus window, then see if it or one of its ancestors
  78.      * is a window in our application (it's possible that the focus
  79.      * window is in an embedded application, which may or may not be
  80.      * in the same process.
  81.      */
  82.  
  83.     XGetInputFocus(dispPtr->display, &window, &dummy);
  84.     while (1) {
  85.         winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, window);
  86.         if ((winPtr2 != NULL) && (winPtr2->mainPtr == winPtr->mainPtr)) {
  87.         break;
  88.         }
  89.         if ((window == PointerRoot) || (window == None)) {
  90.         goto done;
  91.         }
  92.         XQueryTree(dispPtr->display, window, &root, &parent, &children,
  93.             &numChildren);
  94.         if (children != NULL) {
  95.         XFree((void *) children);
  96.         }
  97.         if (parent == root) {
  98.         goto done;
  99.         }
  100.         window = parent;
  101.     }
  102.     }
  103.  
  104.     /*
  105.      * Tell X to change the focus.  Ignore errors that occur when changing
  106.      * the focus:  it is still possible that the window we're focussing
  107.      * to could have gotten unmapped, which will generate an error.
  108.      */
  109.  
  110.     errHandler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1,
  111.         (Tk_ErrorProc *) NULL, (ClientData) NULL);
  112.     if (winPtr->window == None) {
  113.     panic("ChangeXFocus got null X window");
  114.     }
  115.     XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent,
  116.         CurrentTime);
  117.     Tk_DeleteErrorHandler(errHandler);
  118.  
  119.     /*
  120.      * Remember the current serial number for the X server and issue
  121.      * a dummy server request.  This marks the position at which we
  122.      * changed the focus, so we can distinguish FocusIn and FocusOut
  123.      * events on either side of the mark.
  124.      */
  125.  
  126.     winPtr->mainPtr->focusSerial = NextRequest(winPtr->display);
  127.     XNoOp(winPtr->display);
  128.  
  129.     done:
  130.     XUngrabServer(dispPtr->display);
  131.     return;
  132. }
  133.